/*
 *  main.c - main 
 *
 *  Copyright (C) 2011 Intersil Corporation
 *
 */
/*****************************************************************************/
/* CPU        : DP8051                                                       */
/* LANGUAGE   : Keil C                                                       */
/* PROGRAMMER : kimi                                                         */
/*****************************************************************************/

#include <intrins.h>
#include "config.h"
#include "reg.h"
#include "typedefs.h"
#include "TW8835.h"
#include "main.h"
#include "Printf.h"
#include "Monitor.h"
#include "I2C.h"
#include "CPU.h"
#include "SPI.h"
#include "osd.h"
#include "TouchKey.h"


#ifdef	AT070TN83_v01
CODE BYTE CVBS_N[]=
{
	#include "Data\TW8835A_TN82_CVBS_N.txt"
	0xff,0xff,
};
CODE BYTE CVBS_PAL[]=
{
    #include "Data\TW8835A_TN82_CVBS_PAL.txt"
	0xff,0xff,
};
#endif

#ifdef  HSD7D
CODE BYTE GPS_DRGB565[]=
{
    #include "Data\TW8835A_HSD7D_NWD_GPS_DRGB_800_480.txt"
	0xff,0xff,
};
#endif

CODE BYTE A4LCAR_DRGB666[]=
{
    #include "Data\TW8825_AUDI_2014_A4L_400_240_DRGB_800_480.txt"
	0xff,0xff,
};
CODE BYTE A4LBOX_DRGB666[]=
{
    //#include "Data\TW8825_AUDI_2014_A4L_800_480_DRGB_800_480.txt"
    #include "Data\TW8825_AUDI_2014_A4L_800_480_DRGB_800_480_MTK3360.txt"     
	0xff,0xff,
};

DATA BYTE	Stander;
DATA BYTE	count;
DATA BYTE uartdata[2]; 
DATA BYTE SaveLEDLevelData[2]; 
DATA bit UpdataLEDStatus;
XDATA BYTE LVDSMode;
//=============================================================================
//			                                               
//=============================================================================
void InitCore(void)
{
	Puts("\nInitCore");	
	//----- Set SPI mode
	SpiFlashVendor = SPI_QUADInit();
	SPI_Init();

	//----- Enable Chip Interrupt

	WriteTW88Page( PAGE0_GENERAL );
	WriteTW88( 0x02, 0xFF );	// Clear Pending Interrupts
	WriteTW88( 0x03, 0xFE );	// enable SW. disable all other interrupts	
}

void SetMAX9218InputSignalSource(BYTE source)
{
    if(source)
        X_SW = 1;
    else
        X_SW = 0;
}

void SetMAX9218WorkingRange(BYTE mode)
{
    if(mode){
        RNG0 = 1;
        RNG1 = 1;
    }
    else{
        RNG0 = 0;
        RNG1 = 1;
    }
}

void SetLEDBacklightBrightness(BYTE duty)
{
    WriteTW88Page(PAGE0_GENERAL);
    WriteTW88(0xd6, ReadTW88(0xd6) | 0x08);		//enable 
    WriteTW88(0xda, duty);
}

void SetLampEn(BYTE en)
{
	WriteTW88Page(PAGE0_GENERAL);
	if (en)
	{
		WriteTW88(0xd6, ReadTW88(0xd6) | 0x01);
		WriteTW88(0xdd, 0xff);
	}
	else
	{
		WriteTW88(0xd6, ReadTW88(0xd6) & 0xfe);
		WriteTW88(0xdd, 0x00);
	}
}

const BYTE BrightIndexTableWithCAN[] = 
{
	0x00,0x80,0x40,0xC0,
	0x20,0xA0,0x60,0xE0,
	0x10,0x90,0x50,0xD0,
	0x30,0xB0,0x70,0xF0,

	0x08,0x88,0x48,0xC8,
	0x28,0xA8,0x68,0xE8,
	0x18,0x98,0x58,0xD8,
	0x38,0xB8,0x78,0xF8,

	0x04,0x84,0x44,0xC4,
	0x24,0xA4,0x64,0xE4,
	0x14,0x94,0x54,0xD4,
	0x34,0xB4,0x74,0xF4,
};

const BYTE BrightValueTableWithtCAN[] = 
{
	0xBC,0xBA,0xB8,0xB5,
	0xb3,0xb0,0xAE,0xAA,
	0xA8,0xa5,0xa3,0xa0,
	0x9C,0x99,0x96,0x93,

	0x90,0x8D,0x8A,0x87,
	0x84,0x81,0x7D,0x7A,
	0x77,0x74,0x71,0x6E,
	0x6B,0x68,0x65,0x62,

	0x5F,0x5C,0x59,0x56,
	0x54,0x51,0x4F,0x4C,
	0x4A,0x48,0x46,0x44,
	0x42,0x40,0x3F,0x3E,
};

const BYTE BrightIndexTableWithoutCAN[9][2] = 
{
	{0x66,0x66},
	{0x5e,0x07},
	{0xF1,0xDA},
	{0xC5,0x6B},
	{0x1D,0x8A},
	{0x33,0x33},
	{0x87,0x62},
	{0xAF,0x83},
	{0x3F,0xC0},
};

/*
*   70%,  65%,  59%,   53%,  41%,  35%,  30%,  27%
*/
const BYTE BrightValueTableWithoutCAN[9] = 
{
	0xb3,0xa5,0x96,0x87,0x77,0x68,0x59,0x4c,0x44
};

BYTE GetBrightValue(BYTE* index)
{
	BYTE i;

	for (i=0;i<9;i++)
	{
		if (index[0] == BrightIndexTableWithoutCAN[i][0]
			&& index[1] == BrightIndexTableWithoutCAN[i][1])
		{
			return BrightValueTableWithoutCAN[i];
		}
	}

	for (i=0;i<48;i++)
	{
		if (index[0] == BrightIndexTableWithCAN[i])
		{
			return BrightValueTableWithtCAN[i];
		}
	}
	return 0x4C;  //default 0x4C
}

BYTE GetBrightValueByCANData(void)
{
    BYTE tmp;
	CanBrightData = 0xC2;
    if (CanBrightData>0x90)
	{
        tmp = 0xBA-2*(CanBrightData-0x90);
		return tmp;
	}
	else if (CanBrightData>0x80)
	{
		return 0xBD;
	}
	else if (CanBrightData>0x70)
	{
		return 0xC0;
	}
	else if (CanBrightData>0x60)
	{
		return 0xC8;
	}
	else if (CanBrightData>0x50)
	{
		return 0xD0;
	}
	else if (CanBrightData>0x40)
	{
		return 0xD8;
	}
	else 
	{
		return 0xE0;
	}
}

void SetLEDDriver(void)
{
/*
    if((SaveLEDLevelData[0] != uartdata[0]   ) || (SaveLEDLevelData[1] != uartdata[1]))
	{
        UpdataLEDStatus = 1;
        SaveLEDLevelData[0] = uartdata[0];
        SaveLEDLevelData[1] = uartdata[1];
    }
	if(UpdataLEDStatus)
	{
		UpdataLEDStatus = 0;
		BrightnValue = GetBrightValue(SaveLEDLevelData);
		SetLEDBacklightBrightness(BrightnValue);
	}
	*/
	BrightnValue = GetBrightValueByCANData();
	SetLEDBacklightBrightness(BrightnValue);
}

/*
void SetLEDDriver(void)
{
    if((SaveLEDLevelData[0] != uartdata[0]   ) || (SaveLEDLevelData[1] != uartdata[1])){
        UpdataLEDStatus = 1;
        SaveLEDLevelData[0] = uartdata[0];
        SaveLEDLevelData[1] = uartdata[1];
    }
	if(UpdataLEDStatus){
		UpdataLEDStatus = 0;
	    if((SaveLEDLevelData[0] == 0x66) && (SaveLEDLevelData[1] == 0x66))
	        BrightnValue = 0xB3;//0xF0; //70%
	    else if((SaveLEDLevelData[0] == 0x5e) && (SaveLEDLevelData[1] == 0x07))
	        BrightnValue = 0xA5;//0xd2;
	    else if((SaveLEDLevelData[0] == 0xf1) && (SaveLEDLevelData[1] == 0xda))
	        BrightnValue = 0x96;//(0xb4);
	    else if((SaveLEDLevelData[0] == 0xc5) && (SaveLEDLevelData[1] == 0x6b))
	        BrightnValue = 0x87;//(0x96);
	    else if((SaveLEDLevelData[0] == 0x1d) && (SaveLEDLevelData[1] == 0x8a))
	        BrightnValue = 0x77;//(0x78);
	    else if((SaveLEDLevelData[0] == 0x33) && (SaveLEDLevelData[1] == 0x33))
	        BrightnValue = 0x68;//(0x5a);
	    else if((SaveLEDLevelData[0] == 0x87) && (SaveLEDLevelData[1] == 0x62))
	        BrightnValue = 0x59;//(0x3c);
	    else if((SaveLEDLevelData[0] == 0xaf) && (SaveLEDLevelData[1] == 0x83))
	        BrightnValue = 0x4C;//(0x1e);
	    else if((SaveLEDLevelData[0] == 0x3f) && (SaveLEDLevelData[1] == 0xc0))
	        BrightnValue = 0x44;//(0x10);
		else 
		{
			;//SetLEDBacklightBrightness(0x96);
		}

		SetLEDBacklightBrightness(BrightnValue);
    }
}
*/

//GPIO43
void FPBiasOnOff(BYTE fOn)
{
    WriteTW88Page(PAGE0_GENERAL);
    if(fOn) {
    	WriteTW88(0x84, ReadTW88(0x84) | 0x08);		//enable 
    	WriteTW88(0x8C, ReadTW88(0x8C) | 0x08);		//output enable
    	WriteTW88(0x94, ReadTW88(0x94) | 0x08);		//output data 1
    	delay1ms(2);
    }
    else {
        WriteTW88(0x84, ReadTW88(0x84) |     0x08);	//enable
    	WriteTW88(0x8C, ReadTW88(0x8C) | 0x08);	//output enable    //kimi mofidfy    	
    	WriteTW88(0x94, ReadTW88(0x94) &     ~0x08);//output data 0
    }
}

//FrontPanel PowerControl ON - GPIO42.
void FPPWC_OnOff(BYTE fOn)
{	
	WriteTW88Page(PAGE0_GENERAL);
	if(fOn) {
		WriteTW88(0x8C, ReadTW88(0x8C) | 0x04);	//output FPPWC enable
		WriteTW88(0x84, ReadTW88(0x84) | 0x04);	//enable GPIO
		WriteTW88(0x94, ReadTW88(0x94) | 0x04);		//output data 1
	}
	else {
		WriteTW88(0x8C, ReadTW88(0x8C) | 0x04);	//output FPPWC enable    //kimi mofidfy
		WriteTW88(0x84, ReadTW88(0x84) | 0x04);	//enable GPIO
		WriteTW88(0x94, ReadTW88(0x94) &     ~0x04);		//output data 0
	}	
}

void FP_GpioDefault(void)
{
	WriteTW88Page(PAGE0_GPIO);	
	WriteTW88(0x84, 0x00);	//FPBiasOnOff(OFF);
	WriteTW88(0x8C, 0x00);	//FPPWC_OnOff(OFF);
	WriteTW88(0x94, 0x00);	//output	
}

void LEDCOn(BYTE step)
{
	BYTE i;

	WriteTW88Page(PAGE0_LEDC);

	switch(step)
	{
	case 0:
		WriteTW88(0xE0, 0x72);	//default. & disable OverVoltage
		WriteTW88(0xE5, 0x80);	//LEDC digital output enable.
		WriteTW88(0xE0, 0x12);	//Off OverCurrent. Disable Protection
		WriteTW88(0xE0, 0x13);	//LEDC digital block enable
		break;
	case 1:
		WriteTW88(0xE0, 0x11);	//Analog block powerup
		break;
	case 2:
		WriteTW88(0xE0, 0x71);	//enable OverCurrent, enable Protection control
		break;
	default:
		Puts("\nBUG");
		return;
	}
	for(i=0; i < 128; i++) {
		if((ReadTW88(0xE2) & 0x30)==0x30) {	//wait normal
			//dPrintf("\nLEDC2:%bd",i);
			break;
		}
		delay1ms(2);
	}
}

void LEDCGpioOn(void)
{
	WriteTW88Page(PAGE0_GPIO);
	WriteTW88(0x84, 0x0C);	//enable
	WriteTW88(0x8C, 0x0C);	//output enable
	delay1ms(2);	
}

void LedPowerUp(void)
{
#ifdef MSD

    BYTE page;
	page=ReadTW88(0xff);
	WriteTW88Page(PAGE0_LEDC);
	WriteTW88(0xd6, ReadTW88(0xd6) | 0x01);
	WriteTW88(0xdb, ReadTW88(0xdb) & 0xfc);
	delay1ms(2);
	WriteTW88(0xdd, 0x80);
    
    WriteTW88Page(page);
#else
	LEDCOn(0);
	LEDCOn(1);
	LEDCOn(2);
	LEDCGpioOn();
#endif
}

void I2c_init(CODE_P	BYTE  *regset)
{
	BYTE  *index,*value;
	index = regset;
	value = regset+1;
		while(((*index) != 0xff)||((*value) != 0xff))
		{
			WriteTW88(*index, *value);
			index+=2;
			value+=2;
		}
	WriteTW88Page(PAGE0_GENERAL);
}

void SetTW8825DisplayModule(BYTE mode)
{
    if(mode)
    {
		I2c_init(A4LBOX_DRGB666);
	}
    else
    {
    	I2c_init(A4LCAR_DRGB666);
	}
}

#ifdef CVBSSignal
void DetectCVBSSiganl(void)
{
    BYTE page,STD; 
    if(count < 200){
        count++;
        return;
    }        
    else
        count = 0;
    
    page = ReadTW88(0xff);
    WriteTW88Page(PAGE1_DECODER);
    
    while(ReadTW88(0x1c) & 0x80);
    STD = ReadTW88(0x01) & 0xc8;
    
    if(STD == 0x48) {
    #ifdef DEBUG
        Puts("\nCVBS Signal detected");	
    #endif    
        while(ReadTW88(0x1c) & 0x80);
        STD = ReadTW88(0x1c) >> 4;
        
        if(STD == Stander)      return;
        
        switch(STD) {            
            case PAL:
            case SECAM:
            case PALN:
            Stander = PAL;
            break;            
            case NTSC:
            case NTSC4:
            case PALM:            
            case PAL60:
            default:
            Stander = NTSC;
            break;
        }        
    }
    else{
    #ifdef DEBUG
        Puts("\nCVBS Signal no input");	
    #endif
        Stander = NOINPUT;
    }

    if(Stander == NTSC )
        I2c_init(CVBS_N);
    else if(Stander == PAL )
        I2c_init(CVBS_PAL);
    else
        I2c_init(CVBS_N);
        
    WriteTW88Page(page);
}
#endif

#ifdef SUPPORT_GAMMA
#include "Gamma.c"
extern CODE BYTE GammaRed[];
extern CODE BYTE GammaBlue[];
extern CODE BYTE GammaGreen[];


void DownLoadGamma(void)
{
		WriteTW88Page(PAGE2_GAMMA);       //Switch to page 2
		// Red
		WriteTW88(0xe0, 0xe8|1 ); 
		WriteTW88(0xe1, 0x00); //  Start Address
		WriteTW88(0xe3, GammaRed[0]); //  
		I2CWriteDataN(TW88I2CAddress, 0xe3, &GammaRed[1], 255);
		// Blue
		WriteTW88(0xe0, 0xe8|2 ); 
		WriteTW88(0xe1, 0x00); //  Start Address
		WriteTW88(0xe3, GammaGreen[0]); //  
		I2CWriteDataN(TW88I2CAddress, 0xe3, &GammaGreen[1], 255);
		// Red
		WriteTW88(0xe0, 0xe8|3 ); 
		WriteTW88(0xe1, 0x00); //  Start Address
		WriteTW88(0xe3, GammaBlue[0]); //  
		I2CWriteDataN(TW88I2CAddress, 0xe3, &GammaBlue[1], 255);

}
#endif

void TW8825_Disable(void)
{
	WriteTW88Page(PAGE0_GENERAL);
	WriteTW88(0x08, 0xa9);	

	WriteTW88Page(PAGE2_TCON);
	WriteTW88(0x1e, 0x01);	
	WriteTW88(0x1C, 0x44);	
	delay1ms(1);	
}

void TW8825_Enable(void)
{
	WaitVBlank(1);
	WriteTW88Page(PAGE2_TCON);
	WriteTW88(0x1C, 0x42);	
	WriteTW88(0x1e, 0x02);	
	WriteTW88Page(PAGE0_GENERAL);
	WriteTW88(0x08, 0x89);
}

void CheckBoxConnected(void)
{
	if (SystemClock - LastBoxMsgTime>800)  // 800 == 8second
	{
		LastBoxMsgTime  = SystemClock;
		if (LVDSMode != CarLVDSmode)
		{
			LVDSMode = CarLVDSmode;
			TW8825_Disable();
			SetMAX9218WorkingRange(CarLVDSmode);
			SetMAX9218InputSignalSource(CarLVDSmode);
			SetTW8825DisplayModule(CarLVDSmode);
			sendScreenACK(LVDSMode);
			TW8825_Enable();
		}
	}
}


XDATA   DWORD   LampOnDelayTime = 0L;
XDATA   BYTE    bLampOn;
XDATA   BYTE    BrightnValue;
XDATA   BYTE    CanBrightData = 0x91;

void SetLampOnDelay(void)
{
	if (bLampOn == 0)
	{
		if (SystemClock-LampOnDelayTime>50)  // 500ms
		{
			BrightnValue = 250;
			SetLEDBacklightBrightness(BrightnValue);
			SetLampEn(1);
			LampOnDelayTime = SystemClock;
			bLampOn = 1;
		}
	}
	else if (bLampOn < 20)
	{
		if (SystemClock-LampOnDelayTime>15)  // 150ms
		{
			BrightnValue -=8;
			bLampOn++;
			LampOnDelayTime = SystemClock;
			SetLEDBacklightBrightness(BrightnValue);
		}
	}
	else
	{
		SetLampEn(1);
		SetLEDDriver();
	}
}

void main(void)
{
#ifdef PRINT_BOOT_SPEED
    DWORD BootTime;
#endif

    InitCPU();
#ifdef PRINT_BOOT_SPEED
	BootTime = SystemClock;
#endif
	//LVDSMode = CarLVDSmode;
	LVDSMode = BoxLVDSmode;
    SetMAX9218WorkingRange(LVDSMode);
    SetMAX9218InputSignalSource(LVDSMode);
//    SetLEDBacklightBrightness(0x80);
//    FP_GpioDefault();	
//    FPBiasOnOff(OFF);
//    FPPWC_OnOff(OFF);
    InitCore();
    
    Printf("\n********************************************************");
	Printf("\n TW8835 Evaluation Board - %s (%s)", __TIME__, __DATE__);
	Printf("\n********************************************************");

	SetMonAddress(TW88I2CAddress);
	Prompt(); //first prompt

	InitTouch();	
	SetTouchStatus(0);
	SetLastTouchStatus(0);

#ifdef GPSBoard 
//    I2c_init(GPS_DRGB565);
#else
//    I2c_init(CVBS_N);
#endif    

	SetLampEn(0); // Set LAMP_EN pin output LOW
	LampOnDelayTime = SystemClock;
	bLampOn = 0;
    SetTW8825DisplayModule(LVDSMode);
	SetLampEn(0);
//    FPBiasOnOff(ON);

#ifdef SUPPORT_GAMMA
    DownLoadGamma();
#endif
//    FPPWC_OnOff(ON);
//    LedPowerUp();

#ifdef PRINT_BOOT_SPEED
	BootTime = SystemClock - BootTime;
	Printf("\nBootTime:%ld.%ldsec", BootTime/100, BootTime%100 );
#endif
    Prompt();
    EnableEx14Int();
#if 0
 	SspllSetFreqAndPll(108000000L);
	McuSpiClkSet(PCLK_SEL_PLL,SPI_CK_SEL_PCLK,SPI_CK_DIV_1P5);

    delay1ms(20);
//    LoadBackViewParkingGird();
#endif
	SetLEDBacklightBrightness(0x43);
	SetLampEn(1);
    while(1)
    {
        //-------------- Check Serial Port ---------------------
//		Monitor();				// for new monitor functions
#ifndef GPSBoard
//        DetectCVBSSiganl();
#endif	
 //       Drawdongtaiguiji();
        if(I2C_EN == 1)
            continue;
        //GetTouch();	
        //UartRun();
	    //Uart1Run();
        
		//CheckBoxConnected();
		//SetLampOnDelay();
    }
}
